package org.budo.mongo.jdbc.driver;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;

import org.budo.jdbc.driver.AbstractBudoJdbcConnection;
import org.budo.jdbc.driver.exception.BudoJdbcDriverNotSupportedException;
import org.budo.jdbc.driver.statement.JdbcStatement;
import org.budo.mongo.jdbc.driver.config.BudoMongoJdbcDriverConfig;
import org.budo.mongo.jdbc.driver.config.BudoMongoJdbcDriverConfig.Action;

import com.mongodb.MongoClient;
import com.mongodb.client.MongoDatabase;

import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;

/**
 * @author li
 */
@Slf4j
@Setter
@Getter
@Accessors(fluent = true)
public class BudoMongoJdbcConnection extends AbstractBudoJdbcConnection {
    private MongoClient mongoClient;

    private MongoDatabase mongoDatabase;

    public void close() throws SQLException {
        super.close();

        this.mongoClient().close();
    }

    public boolean getAutoCommit() throws SQLException {
        return true;
    }

    public void setAutoCommit(boolean autoCommit) throws SQLException {
        if (!autoCommit) {
            Action whenSetNotAutoCommit = BudoMongoJdbcDriverConfig.getInstance().getWhenSetNotAutoCommit();
            if (Action.IGNORE == whenSetNotAutoCommit) {
                return;
            }

            if (Action.WARN == whenSetNotAutoCommit) {
                log.warn("#71 setAutoCommit(boolean) is not supported, readOnly=" + autoCommit);
                return;
            }

            if (Action.THROW == whenSetNotAutoCommit) {
                throw new BudoJdbcDriverNotSupportedException("#73 setAutoCommit(boolean) is not supported, readOnly=" + autoCommit);
            }
        }
    }

    public int getTransactionIsolation() throws SQLException {
        return Connection.TRANSACTION_NONE;
    }

    public DatabaseMetaData getMetaData() throws SQLException {
        return new BudoMongoJdbcDatabaseMetaData() //
                .connection(this);
    }

    @SuppressWarnings("resource")
    public Statement createStatement() throws SQLException {
        return new BudoMongoJdbcStatement() //
                .connection(this);
    }

    @SuppressWarnings("resource")
    public PreparedStatement prepareStatement(String sql) throws SQLException {
        JdbcStatement jdbcStatement = this.statementParser().parse(sql);

        return (PreparedStatement) new BudoMongoJdbcPreparedStatement() //
                .jdbcStatement(jdbcStatement) //
                .connection(this);//
    }

    /**
     * @see org.budo.mongo.jdbc.driver.BudoMongoJdbcStatement#getGeneratedKeys()
     * @param autoGeneratedKeys {@link java.sql.Statement#RETURN_GENERATED_KEYS
     */
    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
        log.warn("#90 prepareStatement(sql, autoGeneratedKeys) is not supported, sql=" + sql + ", autoGeneratedKeys=" + autoGeneratedKeys);

        return this.prepareStatement(sql);
    }

    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        return this.prepareStatement(sql);
    }
}
